package core;

import random.BuildGraph;
import mesh.MeshGenerator;
import bipartite.BipartiteGraph;
import fixedDegree.RandomGraph;

public class ReportResultsGenerator {
	public static void main(String[] args) throws Exception{
		
		// Uncomment test to run
			
		// runBipartite();
		 runMesh();
		// runFixedDegree();
		// runRandom();
	}
	
	public static void runRandom(){
		int vertices = 10;
		int dense = 5;
		int min = 1;
		int max = 100;
		String fileName;
		
		for(int i = 1; i<=6;i++){
			fileName = "random_"+vertices+"n_"+dense+"m"+"_min"+min+"_max"+max+".txt";
			BuildGraph graph = new BuildGraph();
			graph.BuildRandomGraph(fileName, ".", vertices, dense, max, min);
			TestCase test = new TestCase("random", fileName, vertices+"", dense+"" );
			test.run("Random");
			vertices *= 2;
			dense *= 2;
		}
	}
	
	public static void runMesh() throws Exception{
		int numberOfRows = 5;
		int numberOfColumns = 10;
		int capacity = 1;
		String fileName;
		
		for(int i = 1; i<=5;i++){
			fileName = "mesh_"+numberOfRows+"n_"+numberOfColumns+"m_c"+capacity+".txt";
			String[] args = {numberOfRows+"", numberOfColumns+"", capacity+"", fileName};
			MeshGenerator.main(args);
			TestCase test = new TestCase("mesh", fileName, numberOfRows+"", numberOfColumns+"" );
			test.run("Mesh");
			numberOfRows *= 2;
			numberOfColumns *= 2;
			capacity *= 2;
		}
	}
	
	public static void runBipartite() throws Exception{
		int numberOfNodeOnSourceSide = 10;
		int numberOfNodesOnSinkSide = 5;
		int minCapacity = 1;
		int maxCapacity = 10;
		int probability = 1;
		String fileName;
		
		for(int i = 1; i<=6;i++){
			fileName = "bipartite_"+numberOfNodeOnSourceSide+"n_"+numberOfNodesOnSinkSide+"m_min"+minCapacity+"_max"+maxCapacity;
			String[] args = {numberOfNodeOnSourceSide+"", numberOfNodesOnSinkSide+"", probability+"", minCapacity+"", maxCapacity+"", fileName};
			BipartiteGraph.main(args);
			TestCase test = new TestCase("Bipartite", fileName+".txt", numberOfNodeOnSourceSide+"", numberOfNodesOnSinkSide+"" );
			test.run("Bipartite");
			numberOfNodeOnSourceSide *= 2;
			numberOfNodesOnSinkSide *= 2;
			minCapacity *= 2;
			maxCapacity *= 2;
		}
	}
	
	public static void runFixedDegree() throws Exception{
		int numberOfNodes = 10;
		int numberOfEdges = 5;
		int minCapacity = 1;
		int maxCapacity = 10;
		
		for(int i = 1; i<=6;i++){
			String fileName = "fixedDegree_"+numberOfNodes+"n_"+numberOfEdges+"m_min"+minCapacity+"_max"+maxCapacity+".txt";
			RandomGraph.toFile(RandomGraph.graphBuilder(numberOfNodes,numberOfEdges,minCapacity,maxCapacity),fileName);
			TestCase test = new TestCase("FixedDegree", fileName, numberOfNodes+"", numberOfEdges+"" );
			test.run("FixedDegree");
			numberOfNodes *= 2;
			numberOfEdges *= 2;
			minCapacity *= 2;
			maxCapacity *= 2;
		}
	}
}

class TestCase{
	private String graphType;
	private String algType;
	private String filename;
	private String nodes;
	private String edges;
	private double maxFlow;
	private double time;
	
	public TestCase(String graphType, String filename,
			String nodes, String edges) {
		this.graphType = graphType;
		this.filename = filename;
		this.nodes = nodes;
		this.edges = edges;
	}
	public String getGraphType() {
		return graphType;
	}
	public void setGraphType(String graphType) {
		this.graphType = graphType;
	}
	public String getAlgType() {
		return algType;
	}
	public void setAlgType(String algType) {
		this.algType = algType;
	}
	public String getFilename() {
		return filename;
	}
	public void setFilename(String filename) {
		this.filename = filename;
	}
	public String getNodes() {
		return nodes;
	}
	public void setNodes(String nodes) {
		this.nodes = nodes;
	}
	public String getEdges() {
		return edges;
	}
	public void setEdges(String edges) {
		this.edges = edges;
	}
	public double getMaxFlow() {
		return maxFlow;
	}
	public void setMaxFlow(double maxFlow) {
		this.maxFlow = maxFlow;
	}
	public double getTime() {
		return time;
	}
	public void setTime(double time) {
		this.time = time;
	}
	
	public void run(String graphType){
		String output = "";
		double time = 0;

		SimpleGraph graph;
		graph = new SimpleGraph();
		GraphInput.LoadSimpleGraph(graph, getFilename());
		FordFulkerson fordFulkerson = new FordFulkerson();
		ScalingFordFulkerson scalingFordFulkerson = new ScalingFordFulkerson();
		
		for(int i = 0 ; i < 3; i++){
			final long start = System.nanoTime();			
			setMaxFlow(FFAlt.solve(graph, false));
			final long finish = System.nanoTime();
			setTime(finish-start);
			output += "\n"+graphType+"\t"+getFilename()+"\t"+getNodes()+"\t"+getEdges()+"\tFordFulkerson\t"+getMaxFlow()+"\t"+getTime()+"\t";
			time += getTime();
		}output += (time/3);
		
		for(int i = 0 ; i < 3; i++){
			final long start = System.nanoTime();			
			setMaxFlow(FFAlt.solve(graph, true));
			final long finish = System.nanoTime();
			setTime(finish-start);
			output += "\n"+graphType+"\t"+getFilename()+"\t"+getNodes()+"\t"+getEdges()+"\tScalingFordFulkerson\t"+getMaxFlow()+"\t"+getTime()+"\t";
			time += getTime();
		}output += (time/3);
		
		for(int i = 0 ; i < 3; i++){
			final long start = System.nanoTime();			
			setMaxFlow(PrePush.solve(graph));
			final long finish = System.nanoTime();
			setTime(finish-start);
			output += "\n"+graphType+"\t"+getFilename()+"\t"+getNodes()+"\t"+getEdges()+"\tPrePush\t"+getMaxFlow()+"\t"+getTime()+"\t";
			time += getTime();
		}output += (time/3);
		System.out.println(output);
	}
}
